/**
 *	@file	fld_pmtel.c
 *	@brief	フィールド　電話監視
 *	@author	Miyuki Iwasawa
 *	@date	08.01.28
 */
#include "common.h"

#include "fieldsys.h"
#include "system/pm_str.h"
#include "system/msgdata.h"
#include "system/buflen.h"
#include "system/snd_tool.h"
#include "system/timezone.h"
#include "tel/pmtel_def.h"
#include "tel/pmtel_datman.h"
#include "field/situation_local.h"
#include "field/syswork.h"
#include "field/evwkdef.h"
#include "field/sysflag.h"
#include "field/eventflag.h"
#include "field/onlyone_poke.h"
#include "field/btl_searcher.h"
#include "safari/safari_sys.h"
#include "msgdata/msg.naix"
#include "itemtool/item.h"
#include "savedata/pgear_sv_util.h"

#include "fld_pmtel.h"
#include "tel/pmtel_book.h"
#include "tel/pmtel_dat_def.h"
#include "fld_pmtel_local.h"

///プロトタイプ
static void sub_SafariTelEventCheck(FLD_PMTEL_WORK* wk);

#define PMTEL_DEFAULT_INTERVAL	(10)
#define PMTEL_DEFAULT_PER		(50)
/**
 *	@brief	フィールド　ポケギア電話ワーク確保
 *
 *	必ず FldPMTel_FreeWork()で解放すること
 */
FLD_PMTEL_WORK* FldPMTel_AllocWork(int heapID,FIELDSYS_WORK* fsys)
{
	FLD_PMTEL_WORK* wk;

	wk = sys_AllocMemory(heapID,sizeof(FLD_PMTEL_WORK));
	MI_CpuClear8(wk,sizeof(FLD_PMTEL_WORK));

	FldPMTel_ResetCallParam(wk);

#ifdef DEBUG_ONLY_FOR_iwasawa
	wk->interval = PMTEL_DEFAULT_INTERVAL;
	wk->timeout= 20;
	wk->per= PMTEL_DEFAULT_PER;
#else
	wk->interval = PMTEL_DEFAULT_INTERVAL;
	wk->timeout= 30;
	wk->per= PMTEL_DEFAULT_PER;
#endif
	wk->save = fsys->savedata;
	wk->pgear_sv = SaveData_GetPGearSave(wk->save);
	wk->tel_sv = SaveData_GetPMTelSave(wk->save);
	wk->fsys = fsys;
	return wk;
}

/**
 *	@brief	フィールド　ポケギア電話ワーク解放
 */
void FldPMTel_FreeWork(FLD_PMTEL_WORK* wk)
{
	MI_CpuClear8(wk,sizeof(FLD_PMTEL_WORK));
	sys_FreeMemoryEz(wk);
	wk = NULL;
}

/**
 *	@brief	フィールド　ポケギア電話ワークへのポインタを取得
 */
FLD_PMTEL_WORK* FldPMTel_PointerGet(FIELDSYS_WORK* fsys)
{
	return fsys->pmtel_wk;
}

/**
 *	@brief	フィールド　ポケギア電話　着信フラグセット
 */
void FldPMTel_CallupFlagSet(FLD_PMTEL_WORK* wk)
{
	wk->call_f = TRUE;
	wk->timeout_key = 0;
}

/**
 *	@brief	フィールド　ポケギア電話　着信フラグリセット
 */
void FldPMTel_CallupFlagReset(FLD_PMTEL_WORK* wk)
{
	wk->call_f = FALSE;
}

/**
 *	@brief	フィールド　ポケギア電話　着信フラグゲット
 */
BOOL FldPMTel_CallupFlagGet(FLD_PMTEL_WORK* wk)
{
	return wk->call_f;
}

/**
 *	@brief	ポケギア　電話帳ワークへのポインタを取得
 */
PMTEL_BOOK* FldPMTel_GetBookWorkAdrs(FLD_PMTEL_WORK* wk)
{
	return &wk->book;
}

/**
 *	@brief	電話　着信予約設定
 */
void FldPMTel_IncomingReservation(FLD_PMTEL_WORK* wk,u8 reserve_id,BOOL force_f)
{
	//予約
	PMTelSv_CallReserveSet(wk->tel_sv,reserve_id);

	if(!force_f){
		return;
	}
	//とっとと着信するように、着信までのカウンタを調整
	if(wk->count < (wk->interval-1)){
		wk->count = wk->interval-1;	//一分で着信
	}
}

/**
 *	@brief	電話　着信抽選カウンター更新
 *
 *	@param	diff_time	分単位の差分
 */
void FldPMTel_UpdateTimeCounter(FLD_PMTEL_WORK* wk,int diff_m,int diff_s)
{
	if(wk->finit_f == 0){
		wk->finit_f = 1;
		if(diff_m >= PMTEL_DEFAULT_INTERVAL){
			return;	//最初の一回(ロード時)に差分がデフォルト以上なら一回だけスルー(でないと、ロードしてすぐ必ず着信するため)
		}
	}
	wk->count += diff_m;

#ifdef PM_DEBUG
	if(wk->call_f){
//		GF_ASSERT_MSG(0,"電話着信　タイムアウトエラー %d:%d\n＊このAssertが出たら、岩澤に連絡ください\n",
//			diff_m,diff_s);
		return;
	}
#endif
	//サファリチェック
	sub_SafariTelEventCheck(wk);
}

static void sub_SafariTelEventCheck(FLD_PMTEL_WORK* wk)
{
	EVENTWORK* ev = SaveData_GetEventWork(wk->save);
	SAFARI_SAVE* safari_sv = SaveData_GetSafariSave(wk->save);
	PLAYTIME* playtime = SaveData_GetPlayTime(wk->save);

	u8 mission = SysWork_GetSafariMissionStatus( ev );
	u8	key,level,i;

	//既に着信予約がある
	for(i = 0;i < 5;i++){
		if(PMTelSv_CallReserveCheck(wk->tel_sv,PMTEL_RESERVE_SAFARI_MISSION2_OK+i)){
			return;
		}
	}
	level = SafariSv_GetObjLevel(safari_sv);

	//ミッション1クリア前 or 全OBJ追加後
	if(mission < SAFARI_M1_CLEAR || (level >= SAFARI_OBJ_LEVEL4)){
		return;
	}
	//ミッション1クリア状態
	if(mission == SAFARI_M1_CLEAR){
		key = SafariSv_CheckEventKeyTime(safari_sv,playtime,3);
		if(key == 0){
			return;
		}
		//ミッション2参加OKにする
		FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_MISSION2_OK,TRUE);
		return;
	}
	//ミッション2クリアor全国図鑑open前
	if(	(mission < SAFARI_M2_CLEAR) ||
		(!ZukanWork_GetZenkokuZukanFlag(SaveData_GetZukanWork(wk->save)))){
		return;
	}
	//ミッション2クリア後
	key = SafariSv_CheckEventKeyTime(safari_sv,playtime,3);

	if(key == 0){
		return;
	}else if(key > 1){	//カンスト
		if(level < SAFARI_OBJ_LEVEL3){	//全OBJ追加
			FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_OBJ_ADD_FULL,TRUE);
			return;
		}
		//最後の追加
		FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_OBJ_ADD_END,TRUE);
		return;
	}
	if(level == SAFARI_OBJ_LEVEL0){	//最初の追加
		FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_OBJ_ADD_INI,TRUE);
	}else if(level == SAFARI_OBJ_LEVEL3){	//最後の追加
		FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_OBJ_ADD_END,TRUE);
	}else{
		FldPMTel_IncomingReservation(wk,PMTEL_RESERVE_SAFARI_OBJ_ADD,TRUE);
	}
	return;
}
/**
 *	@brief	電話　着信状態タイムアウトチェック
 */
void FldPMTel_CheckTimeoutCall(FLD_PMTEL_WORK* wk,s64 now_sec)
{
	s32 diff_s;
	if(!wk->call_f){
		return;	//着信状態でなければスルー
	}
	if(wk->timeout_key == 0){
		wk->timeout_key = now_sec;
		return;
	}
	diff_s = now_sec-wk->timeout_key;
//	IWASAWA_PRINT("# PMTEL Call diff=%d\n",diff_s);
	if(diff_s < 0 || (diff_s > wk->timeout) || (diff_s > 59)){
		OS_Printf("# PMTEL Call TimeOut %d  limit=%d\n",diff_s,wk->timeout);
		FldPMTel_EgnoreCall(wk);
		return;
	}
}

/*
 * @brief	電話　着信リセット
*/
void FldPMTel_ResetCallParam(FLD_PMTEL_WORK* wk)
{
	//SE停止
#if 0
	if(wk->se_f){
		Snd_SeStopBySeqNo(SE_PHONE_LOOP,1);
		wk->se_f = FALSE;
	}
#else
	FldPMTel_PhoneSeSet(wk,FALSE);
#endif

	//カウンターリセット
	wk->count = 0;
	wk->timeout_key = 0;

	//着信パラメータリセット
	wk->call_f = FALSE;
	wk->silent_f = FALSE;
	wk->se_f = FALSE;
	wk->number = PMTEL_NUMBER_NULL;
	wk->ev_type = 0;
	wk->ev_id = 0;
	wk->reserve_id = 0;
	wk->book.id = PMTEL_NUMBER_NULL;

#ifdef PM_DEBUG
	if(!wk->deb_per_fix){
		wk->per = PMTEL_DEFAULT_PER;
	}
#else
	wk->per = PMTEL_DEFAULT_PER;	//着信確率リセット
#endif

	OS_Printf("# PMTEL CallEnd\n",0,0,0);
}

/**
 *	@brief	電話　着信無視
 */
void FldPMTel_EgnoreCall(FLD_PMTEL_WORK* wk)
{
	FldPMTel_ResetCallParam(wk);
}

/**
 *	@brief	電話着信　サイレントモードへ移行 → 090605 サイレントモードはなくなる。強制で着信終了 iwasawa
 */
void FldPMTel_SetCallSilentMode(FLD_PMTEL_WORK* wk)
{
	if(!wk->call_f){
		return;
	}
#if 0	//サイレントモードはなくなって、強制着信終了になる
	OS_Printf("# PMTEL Call SilentMode Set\n");

	Snd_SeStopBySeqNo(SE_PHONE_LOOP,1);
	wk->se_f = FALSE;
	wk->silent_f = TRUE;
#else
	FldPMTel_ResetCallParam(wk);
#endif
}

static void tcb_PhoneSePlayTask(TCB_PTR tcb,void* work)
{
	FLD_PMTEL_WORK* wk = (FLD_PMTEL_WORK*)work;

	if(wk->se_wk.ct++ == 0){
		if(Snd_SePlayCheck( SE_PHONE_LOOP ) == FALSE){
			Snd_SePitchPlay( SE_PHONE_LOOP, 0);	//他の音が同チャンネルで再生中なら、この回の再生はスキップ
		}else if(wk->se_wk.ct < 15){
			wk->se_wk.ct = 15;	//次のチェックを少し早くする
		}
	}
	if(wk->se_wk.ct >= 30){
		wk->se_wk.ct = 0;
	}
}

/**
 *	@brief	SE再生タスク
 */
void FldPMTel_PhoneSeSet(FLD_PMTEL_WORK* wk,BOOL set_f)
{
	if(set_f){	//鳴らす
		if(wk->se_f){
			return;
		}
		MI_CpuClear8(&wk->se_wk,sizeof(FLD_PMTEL_SE));
		wk->se_wk.tcb = TCB_Add( tcb_PhoneSePlayTask, wk, 0xFFFFFFFF);	//プライオリティ最下位
		wk->se_f = TRUE;
	}else{	//止める
		if(!wk->se_f){
			return;
		}
		if(wk->se_wk.tcb != NULL){
//			Snd_SeStopBySeqNo(SE_PHONE_LOOP,0);
			TCB_Delete( wk->se_wk.tcb );
		}
		MI_CpuClear8(&wk->se_wk,sizeof(FLD_PMTEL_SE));
		wk->se_f = FALSE;
	}
}

/**
 *	@brief	マサキのボックスいっぱいイベントチェック
 */
BOOL FldPMTel_EvCheckMasakiBoxFull(FIELDSYS_WORK* fsys)
{
	if(PGearSv_IsTelNumberEntry(SaveData_GetPGearSave(fsys->savedata),PMTEL_NUMBER_MASAKI) == PMTEL_NUMBER_NULL){
		return FALSE;
	}
	if(EventWork_CheckEventFlag(
			SaveData_GetEventWork(fsys->savedata),SYS_FLAG_BOX_FULL_INI)){
		return FALSE;
	}
	//ボックスの空き
	if( BOXDAT_GetEmptySpaceTotal(SaveData_GetBoxData(fsys->savedata))){
		return FALSE;
	}
	//予約
	FldPMTel_IncomingReservation(FldPMTel_PointerGet(fsys),PMTEL_RESERVE_MASAKI,TRUE);
	return TRUE;
}

/**
 *	@brief	オーキドの図鑑評価着信イベントチェック
 */
BOOL FldPMTel_EvCheckOokidoZukanCheck(FIELDSYS_WORK* fsys)
{
	int i;
	u16 rank = ZukanWork_GetPokeGetCount(SaveData_GetZukanWork(fsys->savedata));
	EVENTWORK* ev = SaveData_GetEventWork(fsys->savedata);

	if(PGearSv_IsTelNumberEntry(SaveData_GetPGearSave(fsys->savedata),PMTEL_NUMBER_OOKIDO) == PMTEL_NUMBER_NULL){
		return FALSE;
	}

	rank /= TELEV_OOKIDO_ZUKAN_HYOUKA_INTERVAL;

	if(rank == 0){
		return FALSE;
	}else if(rank > TELEV_OOKIDO_ZUKAN_HYOUKA_RANK_MAX){
		rank = TELEV_OOKIDO_ZUKAN_HYOUKA_RANK_MAX;	//最大
	}
	if(!EventWork_CheckEventFlag(ev,SYS_FLAG_ZUKAN_HYOUKA_OVER50+(rank-1))){
		//予約
		FldPMTel_IncomingReservation(FldPMTel_PointerGet(fsys),PMTEL_RESERVE_OOKIDO,FALSE);
		return TRUE;
	}
	return FALSE;
}

/*
 *	@brief	ウツギのトゲピー孵化イベントチェック
 */
BOOL FldPMTel_EvCheckUtsugiTogepiiHatching(FIELDSYS_WORK* fsys,POKEMON_PARAM* pp)
{
	if(!OnlyonePoke_UtsugiTogepiiCheck( pp ,fsys->savedata)){
		return FALSE;
	}
	//予約
	FldPMTel_IncomingReservation(FldPMTel_PointerGet(fsys),
		PMTEL_RESERVE_UTSUGI_TOGEPII_HATCH,TRUE);
	EventWork_SetEventFlag(SaveData_GetEventWork(fsys->savedata),SYS_FLAG_UTSUGI_TOGEPII_HATCHED);
	return TRUE;
}

/**
 *	@brief	育て爺さん　タマゴ発生時の着信イベントチェック
 */
BOOL FldPMTel_EvCheckSodateyaEggSet(FIELDSYS_WORK* fsys)
{
	EVENTWORK* ev_save = SaveData_GetEventWork(fsys->savedata);

	if(PGearSv_IsTelNumberEntry(SaveData_GetPGearSave(fsys->savedata),PMTEL_NUMBER_GRANDPA) == PMTEL_NUMBER_NULL){
		return FALSE;
	}
	if(	(EventWork_CheckEventFlag(ev_save,SYS_FLAG_SODATEYA_EGG_GET_1ST)) &&
		(!EventWork_CheckEventFlag(ev_save,SYS_FLAG_SODATEYA_TEL_ENABLE))){
		return FALSE;
	}
	FldPMTel_IncomingReservation(FldPMTel_PointerGet(fsys),
		PMTEL_RESERVE_GRANDPA,TRUE);
	return TRUE;
}

////////////////////////////////////////////////////////////////////////////
///お母さんの使い込み
////////////////////////////////////////////////////////////////////////////
//使い込みデータケーブル
typedef struct _EMBEZZLEMENT_ITEM{
	u16	itemno;	//アイテムナンバー
	u16	deposit;//金額
	u16	gold;	//値段
}EMBEZZLEMENT_ITEM;
typedef struct _EMBEZZLEMENT_KINOMI{
	u8	kinomi;	//木の実ナンバー
	u8	num;	//個数
	u8	gold;	//金額
}EMBEZZLEMENT_KINOMI;


static const EMBEZZLEMENT_ITEM DATA_MatherEmbezzlementItemTbl[PMTEL_EMBEZZLE_ITEM_MAX] = {
 {ITEM_IIKIZUGUSURI,900,600},
 {ITEM_MUSIYOKESUPUREE,4000,270},
 {ITEM_IIKIZUGUSURI,7000,600},
 {ITEM_SIRUKUNOSUKAAHU,10000,100},
 {ITEM_TUKINOISI,15000,3000},
 {ITEM_SUGOIKIZUGUSURI,19000,900},
 {ITEM_KODAWARISUKAAHU,30000,200},
 {ITEM_TIKARANOHATIMAKI,40000,200},
 {ITEM_KIAINOTASUKI,50000,200},
};

static const EMBEZZLEMENT_KINOMI DATA_MotherEmbezzlementKinomiTbl[PMTEL_EMBEZZLE_KINOMI_MAX] = {
 {ITEMNO_TO_KINOMINO(ITEM_OKKANOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_ITOKENOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_SOKUNONOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_RINDONOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_YATHENOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_YOPUNOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_BIAANOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_SYUKANOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_BAKOUNOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_UTANNOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_TANGANOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_YOROGINOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_KASIBUNOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_HABANNOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_NAMONOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_RIRIBANOMI),5,100},
 {ITEMNO_TO_KINOMINO(ITEM_HOZUNOMI),5,100},
};

/**
 *	@brief	お母さんの使い込みチェック
 */
static BOOL sub_EmbezzleItemCheck(PMTEL_SAVE* tel_sv,u32 n_deposit)
{
	int i,num = 0;
	const EMBEZZLEMENT_ITEM* pt;

	for(i = 0;i < PMTEL_EMBEZZLE_ITEM_MAX;i++){
		if( PMTelSv_PerchaseFinishFlagGet(tel_sv,i) ){
			continue;	//既に購入済み
		}
		//現在の貯金額が基準値を越えているか？
		pt = &DATA_MatherEmbezzlementItemTbl[i];
		if(n_deposit < pt->deposit){
			break;
		}
		//ストック
		PMTelSv_PerchaseFinishFlagSet(tel_sv,i);
		PMTelSv_DepositItemStockAdd(tel_sv,pt->itemno,1);
		//貯金額を減らす
		n_deposit = PMTelSv_DepositControl(tel_sv,PMTEL_DEPOSIT_SUB,pt->gold);

		num++;
		if(PMTelSv_IsDepositItemStockFull(tel_sv)){
			break;
		}
	}
	if(num){
		return TRUE;
	}
	return FALSE;
}

/**
 *	@brief	使い込み発生チェック
 */
int FldPMTel_MatherEmbezzlementCheck(PMTEL_SAVE* tel_sv,u32 n_deposit,u32 o_deposit)
{
	//空きがある？
	if(PMTelSv_IsDepositItemStockFull(tel_sv)){
		return FALSE;
	}

	//使い込み1チェック
	if(sub_EmbezzleItemCheck(tel_sv,n_deposit)){
		return TRUE;
	}
	//3000の倍数を越えたとき
	if((n_deposit/3000) <= (o_deposit/3000)){
		return FALSE;
	}

	//木の実買っちゃう使い込み発生
	{
		const EMBEZZLEMENT_KINOMI* pt;
		pt = &DATA_MotherEmbezzlementKinomiTbl[gf_rand()%PMTEL_EMBEZZLE_KINOMI_MAX];

		PMTelSv_DepositItemStockAdd(tel_sv,KINOMINO_TO_ITEMNO(pt->kinomi),pt->num);
		//貯金額を減らす
		PMTelSv_DepositControl(tel_sv,PMTEL_DEPOSIT_SUB,pt->gold);
	}
	return TRUE;
}


/**
 *	@brief	再戦トレーナーチェック
 *
 *	内部で呼び出すBS_TrainerIDCheck()がオーバレイfield_revengeに配置されてるので呼び出し注意
 *
 */
u16 FldPMTel_RevengeTrainerSearch(u8 tel_number,SAVEDATA* sv,PMTEL_BOOK_MAN* book,u8 time_zone)
{
	u16 id;
	//再戦フラグが有効かチェック
	if(!PMTelSv_RevengeFlagGet(
		SaveData_GetPMTelSave(sv),tel_number)){
		//再戦フラグ無効
		return 0;
	}
	if(tel_number == PMTEL_NUMBER_TR_TAKENORI){
		//タケノリだけは特殊処理でお昼でないと戦えない
		if(time_zone != TIMEZONE_GS_NOON ){
			return 0;
		}
	}
	//再戦が有効なので、再戦時のトレーナーIDを探す
	OS_Printf("tel_num = %d, tr_id = %d",tel_number,book->data[tel_number].tr_id);
    id = BS_TrainerIDCheck( sv, book->data[tel_number].tr_id );
	OS_Printf(" revenge_id %d\n",id);

	return id;
}